using Gameplay.PVE.Entity;
using Gameplay.PVE.Utils;
using UnityEngine;
using Yoozoo.Libs;
using Yoozoo.Managers;

namespace Gameplay.PVE
{
    public class BattleMoveComponent : MoveComponent
    {
        private MoveBehaviour moveBehaviour;
        
        public void Update()
        {
            //((IComponent) this).OnUpdate();
        }
        public void Initialize(UnitBase unit)
        {
            ((IComponent)this).OnInitialize(unit);
        }

        public void Birth()
        {
            ((IComponent)this).OnBirth();
        }
        
        public void Dispose()
        {
            ((IClass)this).OnReset();
        }
        
        protected override void OnUpdate()
        {
            base.OnUpdate();
            if (!PveManager.Instance.isInRpg)
            {
                return;
            }

            if (unit.Data.IsInControl())
            {
                unit.Data.manualForward = Vector3.zero;
                unit.Data.moveState = -1;
            }
            else
            {
                moveBehaviour.Update();
            }
            
            
            UpdateOrders();
            UpdatePosition();
            UpdateForward();

            unit.gameObject.transform.position = unit.Data.position;
            unit.gameObject.transform.forward = unit.Data.forward;
        }
        
        private void UpdateOrders()
        {
            var orders = unit.Data.GetOrders();
            if (orders.Count > 0)
            {
                ObeyOrder(orders[0]);
            }
        }
        
        private BattleUnit hatredUnit;
        
        private float minRegionX = -10;
        private float minRegionY = -5;
        private float maxRegionX = 10f;
        private float maxRegionY = 5;

        private float aiInterval = 1;
        private Vector3 backDirection;
        private float lastAiTime;
        private float xMax;
        private float xMin;
        private float zMax;
        private float zMin;

        protected override void OnTransmit(ETransmitType type, BaseTransmitArg arg)
        {
            if (!PveManager.Instance.isInRpg)
            {
                return;
            }
            base.OnTransmit(type, arg);
            if (type == ETransmitType.RPGStart)
            {
                //unit.Data.birthPosition = unit.Data.position;
                if (unit.Data.team == 0 && unit.Data.rangeType == 0)
                {
                    unit.Data.attackPosition = unit.Data.birthPosition;
                }
                UpdateRoadType();
            }
            else if (type == ETransmitType.ToRPG)
            {
                moveState = 0;
                unit.Data.manualForward = Vector3.zero;
                unit.Data.isMoveAttacking = false;
            }
            else if (type == ETransmitType.ObstacleUpdate)
            {
                if (unit.Data.attackPosition != Vector3.zero)
                {
                    unit.Data.manualForward = Vector3.zero;
                    unit.Data.moveState = 2;
                    unit.Data.isGoingToHidePoint = true;
                    unit.Data.astarPosition = unit.Data.attackPosition;
                    unit.Data.AddAstar();
                    //Debug.LogError(unit.Data.id + " is going to HidePoint");
                }
            }
            else if (type == ETransmitType.AddControl)
            {
                /*if (unit.Data.attackPosition != Vector3.zero &&
                    Vector3.Distance(unit.Data.position, unit.Data.attackPosition) >= 6)
                {
                    roadPath.needRepath = true;
                }*/
            }
            else if (type == ETransmitType.LogicPause)
            {
                unit.Data.manualForward = Vector3.zero;
                unit.Data.moveState = 0;
            }
        }

        protected override void OnBirth()
        {
            base.OnBirth();
            if (PveManager.Instance.isInRpg)
            {
                UpdateRoadType();
            }
            if (unit.Data.team == 0)
            {
                if (unit.Data.rangeType == 1)
                {
                    moveBehaviour = ClassManager.Get<SelfMeleeMoveBehaviour>();
                }
                else
                {
                    moveBehaviour = ClassManager.Get<SelfRangerMoveBehaviour>();
                }
            }
            else
            {
                if (unit.Data.rangeType == 1)
                {
                    moveBehaviour = ClassManager.Get<EnemyMeleeMoveBehaviour>();
                }
                else
                {
                    moveBehaviour = ClassManager.Get<EnemyRangeMoveBehaviour>();
                }
            }
            moveBehaviour.Init(unit,roadPath);
            unit.Data.moveState = 0;
        }

        public void UpdateRoadType()
        {
            int roadType = PveManager.Instance.GetRpgRoadTypeByPosition(unit.Data.position);
            unit.Data.roadType = roadType;
            //unit.Log("roadType"+roadType);
            if (unit.Data.team == 0)
            {
                var region = PveManager.Instance.GetRpgStageRegionByRoadType(roadType);
                xMax = region.y;
                xMin = region.x;
                zMax = region.w;
                zMin = region.z;
            }

            if (unit.Data.team == 0)
            {
                if (roadPath is MoveAttackRoadPath path)
                {
                    path.SetRestriction(xMin, xMax, zMin, zMax);
                }
            }
        }

        private float targetAttackRange;

        private void UpdateEnemyMoveAttack()
        {
            if (unit.Data.IsInSkill() || !unit.Data.IsAttackInRange())
            {
                targetAttackRange = 0;
                unit.Data.manualForward = Vector3.zero;
                return;
            }
            unit.Data.moveState = 2;
            if (unit.Data.lockTarget != null)
            {
                if (targetAttackRange == 0)
                {
                    targetAttackRange = Random.Range(0.8f, 1.2f) * unit.Data.attackRange / 2;
                }

                var distance = Mathf.Abs(unit.Data.position.x - unit.Data.lockTarget.Data.position.x);//Vector3.Distance(unit.Data.position, unit.Data.lockTarget.Data.position);
                if (distance >= targetAttackRange)
                {
                    unit.Data.moveState = 1;
                    unit.Data.manualForward = new Vector3(-1,0,0);//(unit.Data.lockTarget.Data.position - unit.Data.position).normalized;
                }
                else
                {
                    unit.Data.moveState = 0;
                    unit.Data.manualForward = Vector3.zero;
                }
            }
            else
            {
                unit.Data.moveState = 0;
                unit.Data.manualForward = Vector3.zero;
            }
        }

        private UnitBase lastLockTarget;

        private void UpdateEnemyAttackPoint()
        {
            if (unit.Data.IsInSkill() || unit.Data.IsInAttack())
            {
                return;
            }
            
            unit.Data.moveState = 2;
            if (unit.Data.lockTarget != null)// && Vector3.Distance(unit.Data.position,unit.Data.lockTarget.Data.position) > unit.Data.attackRange)
            {
                if (unit.Data.rangeType == 0)
                {
                    
                }
                else
                {
                    if (!unit.Data.hasReachAttackPosition && unit.Data.attackPosition == Vector3.zero && PveGlobalVlues.ZombieFindPathTest)
                    {
                        unit.Data.attackPosition = UnitManager.Instance.GetMeleeAttackPosition() + PveUtils.GetRandomVector3(new Vector3(-1,0,-1f),new Vector3(1,0,1f));
                    }
                    
                }
            }

            if (unit.Data.lockTarget != null && (unit.Data.attackPosition != unit.Data.position || !unit.Data.IsInScreen()))
            {
                
            }
            else
            {
                unit.Data.moveState = 0;
                unit.Data.manualForward = Vector3.zero;
            }
        }

        private void UpdateEnemyMelee()
        {
            if (unit.Data.IsInSkill() || unit.Data.IsInAttack())
            {
                return;
            }
            
            unit.Data.moveState = 2;
            if (unit.Data.lockTarget != lastLockTarget || !unit.Data.IsAttackInRange())
            {
                targetAttackRange = 0;
                unit.Data.attackPosition = Vector3.zero;
                return;
            }

            if (unit.Data.lockTarget != null && Vector3.Distance(unit.Data.attackPosition,unit.Data.position) > 0.1f)
            {
                if (targetAttackRange == 0)
                {
                    targetAttackRange = Random.Range(0.3f,1f) * unit.Data.attackRange;
                    if (targetAttackRange <= 6)
                    {
                        targetAttackRange = 6;
                    }
                    var xDiff = unit.Data.position.x - unit.Data.lockTarget.Data.position.x;
                    var ratio = xDiff / Mathf.Abs(xDiff);
                    var targetPosition = new Vector3(unit.Data.lockTarget.Data.position.x + ratio * targetAttackRange,0,unit.Data.position.z);
                    unit.Data.attackPosition = targetPosition;
                }
                lastLockTarget = unit.Data.lockTarget;
            }
            else
            {
                unit.Data.moveState = 0;
                unit.Data.manualForward = Vector3.zero;
            }
        }
        
        private void UpdateEnemyStandAttack()
        {
            if (unit.Data.IsInSkill() || unit.Data.IsInAttack())
            {
                return;
            }
            
            unit.Data.moveState = 2;
            if (unit.Data.lockTarget != lastLockTarget || !unit.Data.IsAttackInRange())
            {
                targetAttackRange = 0;
                unit.Data.attackPosition = Vector3.zero;
                return;
            }

            if (unit.Data.lockTarget != null && Vector3.Distance(unit.Data.attackPosition,unit.Data.position) > 0.1f)
            {
                if (targetAttackRange == 0)
                {
                    targetAttackRange = Random.Range(0.3f,1f) * unit.Data.attackRange;
                    if (targetAttackRange <= 6)
                    {
                        targetAttackRange = 6;
                    }
                    var xDiff = unit.Data.position.x - unit.Data.lockTarget.Data.position.x;
                    var ratio = xDiff / Mathf.Abs(xDiff);
                    var targetPosition = new Vector3(unit.Data.lockTarget.Data.position.x + ratio * targetAttackRange,0,unit.Data.position.z);
                    unit.Data.attackPosition = targetPosition;
                }
                lastLockTarget = unit.Data.lockTarget;
            }
            else
            {
                unit.Data.moveState = 0;
                unit.Data.manualForward = Vector3.zero;
            }
        }
        
        private void UpdateEnemyAI()
        {
            if (PveGlobalVlues.enemyUseAttackPoint)
            {
                UpdateEnemyAttackPoint();
            }
            else if (unit.Data.isCanMoveAttack)
            {
                UpdateEnemyMoveAttack();
            }
            else
            {
                
                UpdateEnemyStandAttack();
            }

            if (unit.Data.isBoss && PveManager.Instance.rpgStart)
            {
                if (!unit.Data.hasShowBossWarning && unit.Data.IsInScreen())
                {
                    unit.Data.hasShowBossWarning = true;
                }
            }

            if (unit.Data.isElite && PveManager.Instance.rpgStart)
            {
                if (!unit.Data.hasShowBossWarning && unit.Data.IsInScreen())
                {
                    unit.Data.hasShowBossWarning = true;
                }
            }
        }

        private float startBackTime;
        
        private void UpdateSelfMelee()
        {
            if (unit.Data.IsInSkill() || unit.Data.isInAction || unit.Data.isHiding || unit.Data.IsInAttack())
            {
                unit.Data.moveState = -1;
                return;
            }
            if (unit.Data.rangeType == 1 && false)//unit.Data.attackRange > 2)
            {
                if (unit.Data.lockTarget == null && unit.Data.position.x > PveGlobalVlues.SelfMeleeLine2)
                {
                    if (startBackTime == 0)
                    {
                        startBackTime = TimeManager.logicTime + Random.Range(0.3f,0.7f);
                    }
                    else if (TimeManager.logicTime > startBackTime)
                    {
                        unit.Data.SetTargetForward(Vector3.right);
                        unit.Data.forward = Vector3.right;
                        unit.Data.manualForward = (unit.Data.birthPosition - unit.Data.position).normalized;
                        unit.Data.moveState = 1;
                        /*if (unit.Data.heroId == 41005)
                        {
                            unit.Data.forward = Vector3.left;
                        }*/
                        if (Vector3.Distance(unit.Data.birthPosition,unit.Data.position) <= 0.5f)
                        {
                            startBackTime = 0;
                            //unit.Data.forward = Vector3.right;
                        }
                    }
                }
                else
                {
                    startBackTime = 0;
                    unit.Data.manualForward = Vector3.zero;
                    unit.Data.moveState = 2;
                }
            }
            else
            {
                unit.Data.moveState = 2;
            }
        }

        private Vector3 walkDestination;
        private int moveState = 0;
        
        private void DoRandomWalk()
        {
            hatredUnit = null;//unit.Data.hatredTarget;
            if (hatredUnit != null && hatredUnit.Data.isDead)
            {
                hatredUnit = null;
            }
            if (moveState == 0 && (unit.Data.IsInAttack() || unit.Data.isReloading))
            {
                moveState = 1;
            }

            if (moveState == 3 && !unit.Data.isMoveAttacking)
            {
                if (hatredUnit != null)
                {
                    moveState = 2;
                }
                else
                {
                    moveState = 0;
                }
            }
            if (moveState == 0)
            {
                unit.Data.manualForward = Vector3.zero;
                unit.Data.moveState = 0;
            }
            else if (moveState == 1 && !unit.Data.IsInAttack())
            {
                if (hatredUnit != null || Random.Range(0, 1f) < 0.3f)
                {
                    moveState = 2;
                }
                else
                {
                    moveState = 0;
                }
                
            }
            else if (moveState == 2 && unit.Data.isMoveAttacking)
            {
                moveState = 3;
            }
           
            if (moveState == 1 || moveState == 2 || moveState == 3)
            {
                if (hatredUnit != null)
                {
                    var forward = unit.Data.position - hatredUnit.Data.position;
                    bool isCanMove = false;
                    if (lastAiTime == 0)
                    {
                        isCanMove = true;
                        lastAiTime = TimeManager.logicTime;
                    }
                    else if (TimeManager.logicTime - lastAiTime < aiInterval * 2)
                    {
                        isCanMove = true;
                    }
                    /*else if (TimeManager.logicTime - lastAiTime < 4 * aiInterval)
                    {
                        isCanMove = false;
                    }*/
                    else
                    {
                        backDirection = Vector3.zero;
                        lastAiTime = 0;
                    }
                    if (isCanMove && forward.sqrMagnitude <= unit.Data.attackRange * unit.Data.attackRange * 0.7f * 0.7f)
                    {
                        if (backDirection == Vector3.zero)
                        {
                            forward = Quaternion.AngleAxis(Random.Range(-30f,30f),Vector3.up) * forward.normalized;
                            backDirection = forward;
                            
                        }
                        
                        var offset = unit.Data.configMoveSpeed * TimeManager.LogicDeltaTime * backDirection.normalized;
                        
                        
                        var x = offset.x + unit.Data.position.x;
                        var z = offset.z + unit.Data.position.z;
                        float angle = 0;

                        zMin = unit.Data.birthPosition.z - 4;
                        zMax = unit.Data.birthPosition.z + 4;
                        xMin = unit.Data.birthPosition.x - 4;
                        xMax = unit.Data.birthPosition.x + 4;
                        //if (PveManager.Instance.mainUnit != null)
                        {
                            var minRegionY = zMin;
                            var maxRegionY = zMax;
                            var minRegionX = xMin;
                            var maxRegionX = xMax;
                            if (z < minRegionY || z > maxRegionY)
                            {
                                offset = offset.x < 0 ? Vector3.left : Vector3.right;
                            }
                            if (x < minRegionX || x > maxRegionX)
                            {
                                offset = offset.z < 0 ? Vector3.back : Vector3.forward;
                            }
                        }
                        
                        angle = PveUtils.GetAngle(backDirection, offset);
                        if (angle != 0)
                        {
                            angle = angle / Mathf.Abs(angle);
                            angle = Random.Range(0, 60 * angle);
                        }
                       
                        backDirection = Quaternion.AngleAxis(angle,Vector3.up) * offset;
                        
                        unit.Data.manualForward =  backDirection.normalized;
                        unit.Data.moveState = moveState == 1 ? 0 : 1;
                    }
                    else
                    {
                        unit.Data.manualForward = Vector3.zero;
                        unit.Data.moveState = 0;
                    }
                }
                else
                {
                    if (walkDestination == Vector3.zero || Vector3.Distance(unit.Data.position, walkDestination) <=
                        unit.Data.walkSpeed * TimeManager.LogicDeltaTime || PveFindPathManager.Instance.CheckIsOutOfBound(unit.Data.position + unit.Data.walkSpeed * Time.deltaTime * unit.Data.manualForward) || !unit.Data.IsInScreen())
                    {
                        //找新的地点
                        float rad = Random.Range(0, 360f) * Mathf.Deg2Rad;
                        float x = Mathf.Cos(rad);
                        float z = Mathf.Sin(rad);
                        float radius = 1f;
                        walkDestination = unit.Data.birthPosition + new Vector3(radius * x, 0, radius * z);
                        if (!PveFindPathManager.Instance.CheckIsWalkable(walkDestination, unit.Data.id) || PveFindPathManager.Instance.CheckIsOutOfBound(walkDestination))
                        {
                            walkDestination = unit.Data.position;
                            moveState = 1;
                        }
                    }
                    else
                    {

                    }

                    unit.Data.manualForward = walkDestination - unit.Data.position;
                    unit.Data.moveState = moveState == 1 ? 0 : 1;
                }
            }
        }

        private void DoHitAndRun()
        {
            /*if (unit.Data.IsInAttack())
            {
                unit.Data.attackPosition = Vector3.zero;
                return;
            }*/

            if (unit.Data.attackPosition == Vector3.zero)
            {
                unit.Data.attackPosition = unit.Data.birthPosition +
                                           PveUtils.GetRandomVector3(new Vector3(-1, 0, -1), new Vector3(1, 0, 1));
                
            }

            if (unit.Data.IsInAttack() || unit.Data.isReloading || unit.Data.attackPosition == unit.Data.position)
            {
                unit.Data.moveState = 0;
            }
            else
            {
                unit.Data.moveState = 2;
            }
            
        }
        
        private void UpdateSelfStand()
        {
            if (unit.Data.IsInSkill() || unit.Data.isInAction || unit.Data.isHiding)
            {
                if (unit.Data.moveState == 3 || unit.Data.moveState == 4)
                {
                    
                }
                else
                {
                    unit.Data.manualForward = Vector3.zero;
                }
                
                //unit.Data.moveState = -1;
                return;
            }

            
            /*if (unit.Data.rangeType == 1)
            {
                unit.Data.manualForward = Vector3.zero;
                unit.Data.isMoveAttacking = false;
                return;
            }*/

            
            if (PveGlobalVlues.HitAndRun == 0)
            {
                //移动设计
                //if (unit.Data.attackPosition != Vector3.zero)
                {
                    if (unit.Data.isGoingToHidePoint)
                    {
                        unit.Data.moveState = 2;
                        return;
                    }
                }
                if (PveManager.Instance.rpgStart && unit.Data.rpgMoveAttackId > 0)
                {
                    DoRandomWalk();
                    if (unit.Data.isReloading || unit.Data.isInAction || unit.Data.isHiding || unit.Data.isGoingToHidePoint)
                    {
                        unit.Data.moveState = 0;
                    }
                }
            }
            else
            {
                //hit and run
                if (PveManager.Instance.rpgStart)
                {
                    DoHitAndRun();
                }
            }
           

            return;
            var distance = Vector3.Distance(unit.Data.position,unit.Data.birthPosition);
            if (distance >= unit.Data.configMoveSpeed * Time.deltaTime)
            {
                unit.Data.manualForward = (unit.Data.birthPosition - unit.Data.position).normalized;
                unit.Data.moveState = 1;
            }
            else
            {
                unit.Data.manualForward = Vector3.zero;
                unit.Data.moveState = 0;
                //unit.Data.position = unit.Data.birthPosition;
            }
        }
        
        private void UpdateAI()
        {
            if (unit.Data.isManualMoving || unit.Data.team == 2 || unit.Data.IsInSkill() || !unit.Data.isCanMoveAttack || unit.Data.rangeType == 1 || unit.Data.isHiding)
            {
                unit.Data.manualForward = Vector3.zero;
                return;
            }
            unit.Data.moveState = 2;
            
            if (unit.Data.hatredTarget != null)
            {
                if (unit.Data.hatredTarget.Data.isDead)
                {
                    unit.Data.hatredTarget = null;
                    unit.Data.manualForward = Vector3.zero;
                    return;
                }
                hatredUnit = unit.Data.hatredTarget;
            }
            else
            {
                hatredUnit = null;
            }
            /*else if (unit.Data.lockTarget != null && !unit.Data.lockTarget.Data.isDead)
            {
                hatredUnit = unit.Data.lockTarget;
            }*/
            
            if (hatredUnit != null)
            {
                var forward = unit.Data.position - hatredUnit.Data.position;
                bool isCanMove = false;
                if (lastAiTime == 0)
                {
                    isCanMove = true;
                    lastAiTime = TimeManager.logicTime;
                }
                else if (TimeManager.logicTime - lastAiTime < aiInterval * 2)
                {
                    isCanMove = true;
                }
                else if (TimeManager.logicTime - lastAiTime < 4 * aiInterval)
                {
                    isCanMove = false;
                }
                else
                {
                    backDirection = Vector3.zero;
                    lastAiTime = 0;
                }
                if (isCanMove && forward.sqrMagnitude <= unit.Data.attackRange * unit.Data.attackRange * 0.7f * 0.7f)
                {
                    if (backDirection == Vector3.zero)
                    {
                        forward = Quaternion.AngleAxis(Random.Range(-30f,30f),Vector3.up) * forward.normalized;
                        backDirection = forward;
                        
                    }
                    
                    var offset = unit.Data.configMoveSpeed * TimeManager.LogicDeltaTime * backDirection.normalized;
                    
                    
                    var x = offset.x + unit.Data.position.x;
                    var z = offset.z + unit.Data.position.z;
                    float angle = 0;
                    
                    if (PveManager.Instance.mainUnit != null)
                    {
                        var minRegionY = zMin;
                        var maxRegionY = zMax;
                        var minRegionX = xMin;
                        var maxRegionX = xMax;
                        if (z < minRegionY || z > maxRegionY)
                        {
                            offset = offset.x < 0 ? Vector3.left : Vector3.right;
                        }
                        if (x < minRegionX || x > maxRegionX)
                        {
                            offset = offset.z < 0 ? Vector3.back : Vector3.forward;
                        }
                    }
                    
                    angle = PveUtils.GetAngle(backDirection, offset);
                    if (angle != 0)
                    {
                        angle = angle / Mathf.Abs(angle);
                        angle = Random.Range(0, 60 * angle);
                    }
                   
                    backDirection = Quaternion.AngleAxis(angle,Vector3.up) * offset;
                    
                    unit.Data.manualForward =  backDirection.normalized;
                    unit.Data.moveState = 1;
                }
                else
                {
                    unit.Data.manualForward = Vector3.zero;
                    unit.Data.moveState = 0;
                }
            }
            else
            {
                unit.Data.manualForward = Vector3.zero;
                unit.Data.moveState = 0;
            }
        }
    }
}